
itcl::class LocatorType {
	
	constructor {name colorTracker shortHandDict} {
		set iName $name
		set iColorTracker $colorTracker
		set iShortHandDict $shortHandDict
		set iLocators [iarray::Array #auto]
	}
	
	method execute {
		name parent operator
		locations locationNames locationNumbers mapTranslations
		parameters
	} {
		set iSceneName $name
		set iSceneParent $parent
		set iSceneOperator $operator
		set iLocations $locations
		set iLocationNames $locationNames
		set iLocationNumbers $locationNumbers
		set iMapTranslations $mapTranslations
		foreach {action locator} [$iLocators get] {
			set value [$locator getValue]
			set index [$locator getIndex]
			if {$index < 0} continue
			if {$value < 0} {incr index $value}
			set parameter [lindex $parameters $index]
			$locator execute [lindex $parameters $index]
		}
	}
	
	method setParameterOrder {actionValues} {
		set index 0
		foreach {action value} $actionValues {
			assert {[$iLocators has $action]} {
				No such <$action> action exists for location type $name 
			}
			set locator [$iLocators get $action]
			$locator setValue $value
			$locator setIndex $index
			incr index
		}
	}
	
	method addLocator {action locator} {
		$iLocators acquire $action $locator
		$locator setLocatorType $this
	}
	method getLocator {action} {$iLocators get $action}
	method getColorTracker {} {return $iColorTracker}
	method getShortHandDict {} {return $iShortHandDict}
	method getSceneName {} {return $iSceneName}
	method getLocations {} {return $iLocations}
	method getNumberLocations {} {
		if {[string length $iNumberLocations]} {return $iNumberLocations}
		return [$iMapImage getNumberLocations]
	}
	method getSelectedLocations {} {
		if {[llength $iSelectedLocations]} {return $iSelectedLocations}
		if {![llength $iLocationNumbers]} {return [set iSelectedLocations $iLocations]}
		set iSelectedLocations {}
		foreach number $iLocationNumbers {
			lappend iSelectedLocations [lindex $iLocations [expr $number - 1]]
		}
		return $iSelectedLocations
	}
	method getNamedLocations {} {
		if {[llength $iNamedLocations]} {return $iNamedLocations}
		set iNamedLocations {}
		set selectedLocations [getSelectedLocations]
		foreach locInfo [lrange $iLocationNames 0 [expr [llength $selectedLocations] - 1]] loc [lrange $selectedLocations 0 [expr [llength $iLocationNames] - 1]] {
			set located [nameAndLocate $locInfo $loc]
			if {![llength $located]} continue
	
			if {[$iMapTranslations has [lindex $located 0]]} {
				set located [lreplace $located 0 0 [$iMapTranslations of [lindex $located 0]]]
			}
			
			lappend iNamedLocations $located
		}
		return $iNamedLocations
	}
	method getLocationScene {} {
		if {[string length $iLocationScene]} {return $iLocationScene}
		if {$iSceneParent} {
			$iSceneParent updateAttributes [list \$NumberOfScenes [expr [$iSceneParent getAttribute \$NumberOfScenes] + 1]]
			[[$iSceneParent getSequence] of Operators] prependToAct [list "/$iSceneOperator xd"]
			set iLocationScene [createScene $iSceneName $iSceneParent operator $iSceneOperator]
			foreach locInfo [$iLocatorType getNamedLocations] {
				$iLocationScene createActor [eval concat $locInfo]
			}
		}
		return $iLocationScene
	}
	
	variable iName
	variable iLocators
	variable iShortHandDict
	variable iColorTracker
	variable iSceneName
	variable iSceneParent
	variable iSceneOperator
	variable iLocations
	variable iLocationNames
	variable iLocationNumbers
	variable iMapTranslations
	variable iSelectedLocations {}
	variable iNamedLocations {}
	variable iLocationScene {}
}

itcl::class Locator {
	method setLocatorType {locatorType} {set iLocatorType $locatorType}
	method getLocatorType {} {return $locatorType}
	method setValue {value} {set iValue $value}
	method getValue {} {return $iValue}
	method setIndex {index} {set iIndex $index}
	method getIndex {} {return $iIndex}
	
	variable iLocatorType
	variable iValue 0
	variable iIndex -1
}

itcl::class PositionLocator {
	inherit Locator

	method execute {color} {
		if {![string length $color]} return
		set numberPlay [createPlay [$iLocatorType getSceneName] [$iLocatorType getNumberLocations]]
		$numberPlay setFront [list "[[$iLocatorType getColorTracker] addColor $color] bn"]
		$numberPlay setBack en
		set numberScene	[createScene Numbers $numberPlay format "value value" operator nr]
		foreach loc [$iLocatorType getLocations] {
			$numberScene createActor $loc
		}
	}
	
	variable iNumberLocations
}

itcl::class SceneLocator {
	inherit Locator

	method execute {name parent operator} {
	}
	
	method getLocationScene {} {return $iLocationScene}
	
	variable iLocationScene {}
}

itcl::class InfoLocator {
	inherit Locator

	method execute {} {
		if $iMustAct {
			foreach locInfo [$iLocatorType getNamedLocations] {
				$iInfoLocations set [lindex [string toupper [lindex $locInfo 0]] 0] [lindex $locInfo 1]
			}
		}
	}
	
	variable iInfoLocations
}

itcl::class ObjectLocator {
	inherit Locator

	constructor {locatorType action mustAct locationChapter actionPrefix} {
		Locator::constructor locatorType action mustAct
	} {
		set iLocationChapter $locationChapter
		set iActionPrefix $actionPrefix
	}
	
	method execute {actionProc} {
		if $iMustAct {
			$iLocationChapter appendToFront [list "{[expandActionProc $actionProc]} bind"]
		} elseif {[string length $iLocationChapter]} {
			$iLocationChapter appendToFront [list "{\$${iActionPrefix}None} bind"]
		}
	}
	method expandActionProc {actionProc} {
		set shortHandDict [$iLocatorType getShortHandDict]
		if {[$shorthandDict has [string toupper $actionProc]]} {
			return "\$$iActionPrefix[$shorthandDict of [string toupper $actionProc]]"
		}
		assert {[lsearch [$shorthandDict get] $actionProc] >= 0} {
			No such location property <$actionProc>. Choose from one of these (long and short versions): [$shorthandDict get]
		}
		return "\$$iActionPrefix$actionProc"
	}
	
	variable iLocationChapter
	variable iActionPrefix
}

itcl::class ColorLocator {
	inherit Locator
	
	constructor {locatorType action mustAct locationChapter actionPrefix actionObject} {
		Locator::constructor locatorType action mustAct
	} {
		set iLocationChapter $locationChapter
		set iActionPrefix $actionPrefix
		set iActionObjet $actionObject
	}
	
	method execute {color} {
		if $iMustAct {
			if {[string length $color]} {
				$iLocationChapter appendToFront [list "{[[$iLocatorType getColorTracker] addColor $color] \$$iActionPrefix$ActionObject} bind"]
			} else {
				$iLocationChapter appendToFront [list "{\$${iActionPrefix}None} bind"]
			}
		} elseif {[string length $iLocationChapter]} {
			$iLocationChapter appendToFront [list "{\$${iActionPrefix}None} bind"]
		}
	}
	
	variable iLocationChapter
	variable iActionPrefix
	variable iActionObject
}
